package io.adrainty.demo.seata.storage.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.adrainty.demo.seata.account.feign.IAccountFeign;
import io.adrainty.demo.seata.account.models.entity.AccountEntity;
import io.adrainty.demo.seata.storage.mapper.StorageMapper;
import io.adrainty.demo.seata.storage.models.bo.StorageBO;
import io.adrainty.demo.seata.storage.service.IStorageService;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * <p>StorageServiceImpl</p>
 *
 * @author AdRainty
 * @version V1.0.0
 * @description StorageServiceImpl
 * @since 2025/8/20 13:59:24
 */

@Service
public class StorageServiceImpl extends ServiceImpl<StorageMapper, StorageBO> implements IStorageService {

    @Resource
    private IAccountFeign accountFeign;

    @Override
    @GlobalTransactional(name = "do-shop", rollbackFor = Exception.class)
    public Boolean doShop(String accountNo, Long productId, Long skuId, Integer count) {
        StorageBO storageBO = this.lambdaQuery()
                .eq(StorageBO::getProductId, productId)
                .eq(StorageBO::getSkuId, skuId)
                .one();
        if (storageBO == null) {
            throw new RuntimeException("商品不存在");
        }

        if (storageBO.getStock() < count) {
            throw new RuntimeException("库存不足");
        }

        boolean updated = this.lambdaUpdate()
                .eq(StorageBO::getProductId, productId)
                .eq(StorageBO::getSkuId, skuId)
                .eq(StorageBO::getStock, storageBO.getStock())
                .set(StorageBO::getStock, storageBO.getStock() - count)
                .update();
        if (!updated) {
            throw new RuntimeException("库存不足");
        }

        BigDecimal needDecrementBalance = storageBO.getPrice().multiply(new BigDecimal(count)).multiply(BigDecimal.valueOf(-1));
        AccountEntity accountEntity = AccountEntity.builder()
                .accountNo(accountNo)
                .accountBalance(needDecrementBalance)
                .build();
        accountFeign.addAccountBalance(accountEntity);
        return Boolean.TRUE;
    }

}
